#include <iostream>
#include <string>
#include <functional>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>
#include <pthread.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <memory>

#include "InetAddr.hpp"
#include "Log.hpp"
#include "Socket.hpp"

using namespace socket_ns;

class TcpServer;

using io_service_t = std::function<void(socket_sptr sockfd,InetAddr client)>;

class ThreadData
{
    public:
    ThreadData(socket_sptr fd, InetAddr addr, TcpServer *s):_sockfd(fd),
    _clientaddr(addr),_self(s)
    {}
    public:
    socket_sptr _sockfd;
    InetAddr _clientaddr;
    TcpServer *_self ;
};

class TcpServer
{
    public:
    TcpServer(int port, io_service_t service) 
        : _localaddr("0", port),
          _listensock(std::make_unique<TcpSocket>()),
          _service(service),
          _running(false)
    {
        _listensock->BuildListenSocket(_localaddr);
    }
    static void* HandlerSock(void* args)
    {
        pthread_detach(pthread_self());
        ThreadData *td = static_cast<ThreadData *>(args);
        td->_self->_service(td->_sockfd,td->_clientaddr);
        ::close(td->_sockfd->SockFd());
        delete td;
        return nullptr;
    }
    void Loop()
    {
        _running = true;
        while(_running)
        {
            InetAddr peeraddr;
            socket_sptr normalsock = _listensock->Accepter(&peeraddr);
            if(normalsock ==nullptr)continue;
            pthread_t t;
            ThreadData *td = new ThreadData(normalsock, peeraddr, this);
            pthread_create(&t, nullptr, HandlerSock, td); //将线程分离
            
        }
        _running = false;
    }
    private:
    InetAddr _localaddr;
    std::unique_ptr<Socket> _listensock;
    bool _running;
    io_service_t _service;
};